/**
 * The MIT License (MIT)
 *
 * Copyright (c) 2021 Marcus Britanicus (https://gitlab.com/marcusbritanicus)
 * Copyright (c) 2021 Abrar (https://gitlab.com/s96Abrar)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 **/

#pragma once

#include <QObject>
#include <QSize>
#include <QRect>

struct wl_seat;
struct wl_array;
struct wl_output;

struct xdg_surface;
struct xdg_toplevel;
struct xdg_surface_listener;
struct xdg_toplevel_listener;

namespace WQt {
    class XdgTopLevel;
}

class WQt::XdgTopLevel : public QObject {
    Q_OBJECT;

    public:
        enum class State {
            /** The Surface is maximized. */
            Maximized   = 1 << 0,
            /** The Surface is fullscreen. */
            Fullscreen  = 1 << 1,
            /** The Surface is currently being resized by the Compositor. */
            Resizing    = 1 << 2,
            /** The Surface is considered active. Does not imply keyboard focus. */
            Activated   = 1 << 3,
            /** The Surface tiled to Left edge. */
            TiledLeft   = 1 << 4,
            /** The Surface tiled to Top edge. */
            TiledTop    = 1 << 5,
            /** The Surface tiled to Right edge. */
            TiledRight  = 1 << 6,
            /** The Surface tiled to Bottom edge. */
            TiledBottom = 1 << 7,
        };
        Q_DECLARE_FLAGS( States, State );

        XdgTopLevel( xdg_surface *surf, xdg_toplevel *toplevel );
        ~XdgTopLevel();

        void setParent( XdgTopLevel * );
        void setTitle( QString );
        void setAppId( QString );
        void showWindowMenu( wl_seat *seat, quint32 serial, const QPoint& pos );
        void move( wl_seat *seat, quint32 serial );
        void resize( wl_seat *seat, quint32 serial, Qt::Edges );
        void setMaximumSize( const QSize& size );
        void setMinimumSize( const QSize& size );
        void setMaximized();
        void unsetMaximized();
        void setFullscreen( wl_output *output );
        void unsetFullscreen();
        void setMinimized();

        QSize size();
        void setSize( QSize );

        xdg_toplevel *get();
        xdg_surface *xdgSurface();

    private:
        static void handleSurfaceConfigure( void *data, struct xdg_surface *surf, uint32_t serial );

        static void handleTopLevelConfigure( void *data, struct xdg_toplevel *tl, int32_t width, int32_t height, struct wl_array *states );
        static void handleTopLevelClose( void *data, struct xdg_toplevel *tl );

        xdg_toplevel *mObj;
        xdg_surface *mSurfObj;

        static const xdg_toplevel_listener mListener;
        static const xdg_surface_listener mSurfListener;

        QSize pendingSize;
        States pendingStates;
        QSize tlSize;

    Q_SIGNALS:
        void configureRequested( const QSize& size, WQt::XdgTopLevel::States states, quint32 serial );
        void closeRequested();
        void resized( QSize );
};

Q_DECLARE_OPERATORS_FOR_FLAGS( WQt::XdgTopLevel::States );

Q_DECLARE_METATYPE( WQt::XdgTopLevel::State );
Q_DECLARE_METATYPE( WQt::XdgTopLevel::States );
